package dao

import (
	"context"
	"goadmin/model"
	"time"

	"go.mongodb.org/mongo-driver/bson"
)

func GetConversationListByUserId(userId uint) ([]model.Conversation, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	cursor, err := mdb.Collection("conversation").Find(ctx, bson.M{"userId": userId})
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)
	var conversations []model.Conversation
	if err := cursor.All(ctx, &conversations); err != nil {
		return nil, err
	}
	return conversations, nil
}

func GetOrCreateSingleConversation(userId, targetId uint) (model.Conversation, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	var conversation model.Conversation
	err := mdb.Collection("conversation").FindOne(ctx, bson.M{
		"userId":   userId,
		"type":     model.ConversationTypeSingle,
		"targetId": targetId,
	}).Decode(&conversation)
	if err != nil {
		if err.Error() == "mongo: no documents in result" {
			conversation = model.Conversation{
				UserId:   userId,
				Type:     model.ConversationTypeSingle,
				TargetId: targetId,
			}
			_, err = mdb.Collection("conversation").InsertOne(ctx, conversation)
		}
	}
	return conversation, err
}

func RemoveConversation(userId, targetId uint) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	_, err := mdb.Collection("conversation").DeleteOne(ctx, bson.M{
		"userId":   userId,
		"type":     model.ConversationTypeSingle,
		"targetId": targetId,
	})
	return err
}

func UpdateConversationLastMsg(conversation model.Conversation, msg model.Msg, isRecv bool) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	inc := 0
	if !isRecv {
		inc = 1
	}
	_, err := mdb.Collection("conversation").UpdateOne(ctx, bson.M{
		"userId":   conversation.UserId,
		"type":     conversation.Type,
		"targetId": conversation.TargetId,
	}, bson.M{
		"$set": bson.M{"latestMsg": msg},
		"$inc": bson.M{"unread": inc},
	})
	return err
}

func ClearConversationUnread(userId, targetId uint) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	_, err := mdb.Collection("conversation").UpdateOne(ctx, bson.M{
		"userId":   userId,
		"type":     model.ConversationTypeSingle,
		"targetId": targetId,
	}, bson.M{
		"$set": bson.M{"unread": 0},
	})
	return err
}

func SetConversationTop(userId, targetId uint, top int64) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	_, err := mdb.Collection("conversation").UpdateOne(ctx, bson.M{
		"userId":   userId,
		"type":     model.ConversationTypeSingle,
		"targetId": targetId,
	}, bson.M{
		"$set": bson.M{"top": top},
	})
	return err
}
